﻿#include "TextHolder.h"

#undef max
#undef min
#include <fast_io/fast_io_freestanding.h>
#include <Windows.h>

void GamerTextHolder::copyFrom(TextHolder *copy) {
	typedef void *(__cdecl * _malloctype)(size_t);

	static auto _malloc = reinterpret_cast<_malloctype>(GetProcAddress(GetModuleHandleA("api-ms-win-crt-heap-l1-1-0"), "malloc"));

	deleteText();
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
	textLength = copy->textLength;
	alignedTextLength = copy->alignedTextLength;
	if (copy->textLength < 16) {
		fast_io::freestanding::my_memcpy(inlineText, copy->inlineText, 16);
	} else {
		size_t size = copy->textLength;

		if (size + 1 >= 0x1000)
			size += 8;

		pText = reinterpret_cast<char8_t *>(_malloc(size + 1));

		if (size + 1 >= 0x1000) {
			*reinterpret_cast<char8_t **>(pText) = pText;
			pText += 8;
		}

		if (pText != 0x0 && copy->pText != 0x0) {
			fast_io::freestanding::my_memcpy(pText, copy->pText, textLength);
			pText[textLength] = 0;
		}
	}
}

void GamerTextHolder::deleteText() {
	typedef void(__cdecl * _freetype)(void *);
	static auto _free = reinterpret_cast<_freetype>(GetProcAddress(GetModuleHandleA("api-ms-win-crt-heap-l1-1-0"), "free"));

	if (textLength >= 16 && pText != nullptr) {
		if (textLength + 1 >= 0x1000) {
			pText = *reinterpret_cast<char8_t **>(reinterpret_cast<uintptr_t>(pText) - 8);
		}
		_free(pText);
	}
}

#if 0
TextHolder::TextHolder()  {
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
}

TextHolder::TextHolder(TextHolder const &copy)  {
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
	textLength = copy.textLength;
	alignedTextLength = copy.alignedTextLength;
	if (copy.textLength < 16)
		fast_io::freestanding::my_memcpy(inlineText, copy.inlineText, 16);
	else {
		size_t size = textLength + 1;

		if (size + 1 >= 0x1000)
			size += 8;

		pText = reinterpret_cast<char8_t *>(malloc(size + 1));
		alignedTextLength = size;
		if (pText != nullptr) {
			if (size + 1 >= 0x1000) {
				*reinterpret_cast<char8_t **>(pText) = pText;
				pText += 8;
			}

			if (copy.pText != nullptr) {
				fast_io::freestanding::my_memcpy(pText, copy.pText, size);
				pText[size] = 0;
			}
		}
	}
}

TextHolder &TextHolder::operator=(TextHolder const &copy)  {
	deleteText();
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
	textLength = copy.textLength;
	alignedTextLength = copy.alignedTextLength;
	if (copy.textLength < 16)
		fast_io::freestanding::my_memcpy(inlineText, copy.inlineText, 16);
	else {
		size_t size = textLength + 1;

		if (size + 1 >= 0x1000)
			size += 8;

		pText = reinterpret_cast<char8_t *>(malloc(size + 1));
		alignedTextLength = size;
		if (pText != nullptr) {
			if (size + 1 >= 0x1000) {
				*reinterpret_cast<char8_t **>(pText) = pText;
				pText += 8;
			}

			fast_io::freestanding::my_memcpy(pText, copy.pText, textLength);
			pText[textLength] = 0;
		}
	}
	return *this;
}

TextHolder::TextHolder(const std::u8string_view str)  {
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
	textLength = str.size();
	alignedTextLength = textLength | 0xF;
	if (str.size() < 16) {
		fast_io::freestanding::my_memcpy(inlineText, str.data(), str.size());
		if (str.size() < 15)
			inlineText[str.size()] = 0;
	} else {
		size_t size = str.size();
		if (size + 1 >= 0x1000)
			size += 8;

		pText = reinterpret_cast<char8_t *>(malloc(size + 1));
		alignedTextLength = size;
		if (pText != nullptr) {
			if (size + 1 >= 0x1000) {
				*reinterpret_cast<char8_t **>(pText) = pText;
				pText += 8;
			}

			fast_io::freestanding::my_memcpy(pText, str.data(), str.size());
			pText[str.size()] = 0;
		}
	}
}

TextHolder::TextHolder(size_t allocSize)  {
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
	textLength = 0;
	alignedTextLength = allocSize | 0xF;
	if (alignedTextLength < 16) {
		fast_io::freestanding::my_memset(&inlineText, 0, 16);
	} else {
		size_t size = alignedTextLength;
		if (size + 1 >= 0x1000)
			size += 8;

		pText = reinterpret_cast<char8_t *>(malloc(size + 1));
		alignedTextLength = size;
		if (pText != nullptr) {
			if (size + 1 >= 0x1000) {
				*reinterpret_cast<char8_t **>(pText) = pText;

				pText += 8;
				fast_io::freestanding::my_memset(pText, 0, alignedTextLength - 8);
			} else
				fast_io::freestanding::my_memset(pText, 0, alignedTextLength);
		}
	}
}

TextHolder::TextHolder(void *ptr, size_t sizeOfData)  {
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
	textLength = sizeOfData;
	alignedTextLength = sizeOfData;
	if (alignedTextLength < 16)
		fast_io::freestanding::my_memcpy(inlineText, ptr, sizeOfData);
	else
		pText = reinterpret_cast<char8_t *>(ptr);
}

void TextHolder::deleteText()  {
	if (alignedTextLength >= 16 && pText != nullptr) {
		if (alignedTextLength + 1 >= 0x1000) {
			pText = *reinterpret_cast<char8_t **>(reinterpret_cast<uintptr_t>(pText) - 8);
		}
		free(pText);
	}
}

TextHolder::~TextHolder()  {
	this->deleteText();
}

void TextHolder::setText(std::u8string_view str)  {
	this->deleteText();
	fast_io::freestanding::my_memset(this, 0, sizeof(TextHolder));
	textLength = str.size();
	alignedTextLength = textLength | 0xF;
	if (str.size() < 16) {
		fast_io::freestanding::my_memcpy(inlineText, str.data(), str.size());
		if (str.size() < 15)
			inlineText[str.size()] = 0;
	} else {
		size_t size = str.size();
		if (size + 1 >= 0x1000)
			size += 8;

		pText = reinterpret_cast<char8_t *>(malloc(size + 1));
		alignedTextLength = size;
		if (pText != nullptr) {
			if (size + 1 >= 0x1000) {
				*reinterpret_cast<char8_t **>(pText) = pText;
				pText += 8;
			}

			fast_io::freestanding::my_memcpy(pText, str.data(), str.size());
			pText[str.size()] = 0;
		}
	}
}
#endif  // 0
